package starter.api;

import org.elasticsearch.index.query.*;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.web.bind.annotation.*;
import starter.model.Person;
import starter.repository.UserRepository;

import java.util.List;
import java.util.Optional;


/**
 * @author 上等的猪头肉
 * @Title: UserController
 * @ProjectName ElasticsearchSpringData
 * @Description: TODO
 * @date 2018/10/24 10:07
 */
@RestController
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    /**
     * 添加
     * @return
     */
    @GetMapping("add")
    public String add(Person user){
        user.setId(String.valueOf(System.currentTimeMillis()));
        user.setTime(System.currentTimeMillis());
        Person save = userRepository.save(user);
        System.out.println(user.toString());
        return "success";
    }

    /**
     * 删 id
     * @param id
     * @return
     */
    @GetMapping("delete")
    public Integer insertBook( String id) {
//        Optional<Person> byId = userRepository.findById(id);
//        userRepository.delete(byId.get());
//        return 1;
//
        Optional<Person> byId = userRepository.findById(id);
        Integer integer = userRepository.deleteByAndId(byId.get().getId());
        return integer;
    }


    /**
     * 根据id 查询数据
     * @param id
     * @return
     */
    @GetMapping("findById")
    public  Person  idsQuery(String id){
        Optional<Person> byId = userRepository.findById(id);
        return byId.get();
    }


    /**
     * match query 单个匹配
     * @param status
     * @return
     */
    @GetMapping("findByStatus")
    public Iterable<Person> matchQuery(String status){
        QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("status", status);
        Iterable<Person> search = userRepository.search(matchQueryBuilder);
        return search;
    }


    /**
     *  boolean query and 条件组合查询
     */
    @GetMapping
    public Iterable<Person> boolQuery(){
      QueryBuilder queryBuilder =    QueryBuilders
                .boolQuery()
                .must(QueryBuilders.termQuery("name", "葫芦3033娃"))
                .must(QueryBuilders.termQuery("home", "山西省太原市7967街道"))
                .mustNot(QueryBuilders.termQuery("isRealMen", false))
                .should(QueryBuilders.termQuery("now_home", "山西省太原市"));
        Iterable<Person> search = userRepository.search(queryBuilder);
        return search;
    }


    /**
     * disjunction max query
     *  一个生成的子查询文件产生的联合查询，
     *  而且每个分数的文件具有最高得分文件的任何子查询产生的，
     *  再加上打破平手的增加任何额外的匹配的子查询。
     * @param username
     * @return
     */
    @GetMapping("query")
    public  Iterable<Person> sdf(String username){
        DisMaxQueryBuilder disMaxQueryBuilder = QueryBuilders.disMaxQuery()
                .add(QueryBuilders.termQuery("username", username))
                .boost(1.2f)
                .tieBreaker(0.7f);
        Iterable<Person> search = userRepository.search(disMaxQueryBuilder);
        return search;
    }


    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * matchall query
     * 查询匹配所有文件。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    @GetMapping("findAll")
    public  Iterable<Person> matchAllQuery() {
        QueryBuilder QueryBuilder = QueryBuilders.matchAllQuery();
        Iterable<Person> search = userRepository.search(QueryBuilder);
        return search;
    }


    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * prefix query
     * 包含与查询相匹配的文档指定的前缀。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    @GetMapping("findByUsername")
    public  Iterable<Person> prefixQuery(String name) {
        QueryBuilder username = QueryBuilders.prefixQuery("username", name);
        Iterable<Person> search = userRepository.search(username);
        return search;
    }


    /**
     * 一个查询相匹配的多个value
     * @return
     */
    @GetMapping("findByUsernameandusername")
    public  Iterable<Person> termsQuery(String username,String password) {
        QueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(password,
                username, username);
        // 设置最小数量的匹配提供了条件。默认为1。// values
        Iterable<Person> search = userRepository.search(termsQueryBuilder);
        return search;
    }


    /**
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * wildcard query
     * 　　实现了通配符搜索查询。支持通配符* < /tt>,<tt>
     * 　　匹配任何字符序列(包括空),<tt> ? < /tt>,
     * 　　匹配任何单个的字符。注意该查询可以缓慢,因为它
     * 　　许多方面需要遍历。为了防止WildcardQueries极其缓慢。
     * 　　一个通配符词不应该从一个通配符* < /tt>或<tt>
     * 　　< /tt> <tt> ?。
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */
    @GetMapping("queryUsername")
    public  Iterable<Person> wildcardQuery(String username) {
        QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("username", username+"*");
        Iterable<Person> search = userRepository.search(queryBuilder);
        return search;
    }


    /**
     * 实现分页
     * @param page
     * @param size
     * @return
     */
    @GetMapping("page")
   public Page<Person> pagePerson(String page,String size){
       // 分页参数
       Pageable pageable = new PageRequest(Integer.valueOf(page), Integer.valueOf(size));
       QueryBuilder QueryBuilder = QueryBuilders.matchAllQuery();
       // 分数、分页
       SearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageable)
               .withQuery(QueryBuilder).build();

       Page<Person> searchPageResults = userRepository.search(searchQuery);
       return searchPageResults;
   }

    /**
     * 实现排序
     *
     *
     * @param page
     * @param size
     * @return
     */
    @GetMapping("pagesort")
    public Page<Person> pagePersonsort(String aaa,String size,String username){
        //1.创建QueryBuilder(即设置查询条件)这儿创建的是组合查询(也叫多条件查询),后面会介绍更多的查询方法
        /*组合查询BoolQueryBuilder
         * must(QueryBuilders)   :AND
         * mustNot(QueryBuilders):NOT
         * should:               :OR
         */
        BoolQueryBuilder builder = QueryBuilders.boolQuery();

        //builder下有must、should以及mustNot 相当于sql中的and、or以及not

        //设置模糊搜索,博客的简诉中有学习两个字
        builder.must(QueryBuilders.fuzzyQuery("username", username));


        FieldSortBuilder  sort = SortBuilders.fieldSort("time").order(SortOrder.DESC);

        //设置分页(从第一页开始，一页显示10条)
        //注意开始是从0开始，有点类似sql中的方法limit 的查询
        PageRequest pdage = new PageRequest(Integer.valueOf(aaa), Integer.valueOf(size));

        //2.构建查询
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        //将搜索条件设置到构建中
        nativeSearchQueryBuilder.withQuery(builder);
        //将分页设置到构建中
        nativeSearchQueryBuilder.withPageable(pdage);
        //将排序设置到构建中
        nativeSearchQueryBuilder.withSort(sort);
        //生产NativeSearchQuery
        NativeSearchQuery query = nativeSearchQueryBuilder.build();



        //3.执行方法1
        Page<Person> page  =  userRepository.search(query);
//
//        //执行方法2：注意，这儿执行的时候还有个方法那就是使用elasticsearchTemplate
//        //执行方法2的时候需要加上注解
//        //@Autowired
//        //private ElasticsearchTemplate elasticsearchTemplate;
//        List<Person> blogList = elasticsearchTemplate.queryForList(query, Person.class);
//
//        //4.获取总条数(用于前端分页)
//        int total = (int) page.getTotalElements();
//
//        //5.获取查询到的数据内容（返回给前端）
//        List<Person> content = page.getContent();


        return page;
    }


/**
 *
 */

}
